package com.bizframework.springhb.support.dao;

import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.bizframework.core.domain.*;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.criterion.Restrictions;

import com.bizframework.springhb.support.dao.BaseDaoHBImpl;

public class BaseFactoryDaoHBImpl<T extends BaseEntity<IDT>, IDT extends Serializable> extends
		BaseDaoHBImpl<T, IDT> {

	public BaseFactoryDaoHBImpl() {
		super();
	}

	public <SubT extends T> List<SubT> findByByType(Class<SubT> type,
			String name, Object value) {
		return findByByType(type, new String[] { name }, new Object[] { value });
	}

	@SuppressWarnings("unchecked")
	public <SubT extends T> List<SubT> findByByType(Class<SubT> type,
			String[] names, Object[] values) {
		if (names == null || values == null || names.length != values.length) {
			// throw new Exception();
			return null;
		}
		Criteria criteria = this.getCriteria(type);
		Map<String, Object> criteriaMap = new HashMap<String, Object>();
		for (int i = 0; i < names.length; i++) {
			criteriaMap.put(names[i], values[i]);
		}
		criteria.add(Restrictions.allEq(criteriaMap));
		return criteria.list();
	}

	protected <SubT extends T> Criteria getCriteria(Class<SubT> type) {
		Criteria criteria = getSession().createCriteria(type);
		criteria.setCacheable(true);
		criteria.setCacheRegion("com.framework.core");
		return criteria;
	}

	@SuppressWarnings("unchecked")
	public <SubT extends T> List<SubT> getAllByType(Class<SubT> type) {
		return this.getHibernateTemplate().loadAll(type);
	}

	@SuppressWarnings("unchecked")
	public <SubT extends T> List<SubT> getByConditionsByType(Class<SubT> type,
			List<QueryCondition> conditions, int startIndex, int count,
			SortInfo sortInfo) {
		String alias = type.getName().toLowerCase().replace(".", "_");
		String hsql = "From " + type.getName() + " as " + alias + " Where 1=1";
		if (conditions != null) {
			for (QueryCondition condition : conditions) {
				hsql += " " + condition.getQueryLogic() + " " + alias + "."
						+ condition.getFieldName() + " "
						+ condition.getQueryOperator() + " "
						+ condition.getFieldValueString();
			}
		}
		if (sortInfo != null) {
			if (sortInfo.getName() != null && sortInfo.getName() != "") {
				String dir = sortInfo.getSortDirection().toString();
				hsql += " Order By " + alias + "." + sortInfo.getName() + " "
						+ dir;
			}
		}

		Query query = getSession().createQuery(hsql);
		query.setFirstResult(startIndex);
		query.setMaxResults(count);
		List<SubT> results = query.list();
		return results;
	}

	@SuppressWarnings("unchecked")
	public <SubT extends T> List<SubT> getByConditionsByType(Class<SubT> type,
			List<QueryCondition> conditions, SortInfo sortInfo) {
		String alias = type.getName().toLowerCase().replace(".", "_");
		String hsql = "From " + type.getName() + " as " + alias + " Where 1=1";
		if (conditions != null) {
			for (QueryCondition condition : conditions) {
				hsql += " " + condition.getQueryLogic() + " " + alias + "."
						+ condition.getFieldName() + " "
						+ condition.getQueryOperator() + " "
						+ condition.getFieldValueString();
			}
		}
		if (sortInfo != null) {
			if (sortInfo.getName() != null && sortInfo.getName() != "") {
				String dir = sortInfo.getSortDirection().toString();
				hsql += " Order By " + alias + "." + sortInfo.getName() + " "
						+ dir;
			}
		}

		Query query = getSession().createQuery(hsql);
		List<SubT> results = query.list();
		return results;
	}

	public <SubT extends T> ListResult<SubT> getByConditionsWithCountByType(
			Class<SubT> type, List<QueryCondition> conditions, int startIndex,
			int count, SortInfo sortInfo) {
		int total = this.getCountByConditionsByType(type, conditions);
		List<SubT> list = this.getByConditionsByType(type, conditions,
				startIndex, count, sortInfo);
		return new ListResult<SubT>(total, list);
	}

	@SuppressWarnings("unchecked")
	public <SubT extends T> SubT getByIdByType(Class<SubT> type, IDT entityId,
			boolean shouldLock) {
		return (SubT) this.getHibernateTemplate().get(type,
				(Serializable) entityId);
	}

	public <SubT extends T> int getCountByConditionsByType(Class<SubT> type,
			List<QueryCondition> conditions) {
		String alias = type.getName().toLowerCase().replace(".", "_");
		String hsql = "Select count(*) From " + entityClass.getName()
				+ " Where 1=1 ";

		if (conditions != null) {
			for (QueryCondition condition : conditions) {
				hsql += " " + condition.getQueryLogic() + " " + alias + "."
						+ condition.getFieldName() + " "
						+ condition.getQueryOperator() + " "
						+ condition.getFieldValueString();
			}
		}

		Query query = getSession().createQuery(hsql);
		Object o = query.uniqueResult();
		return o == null ? 0 : Integer.parseInt(o.toString());
	}

}
